home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / emacs / src / alloca.s < prev    next >
Text File  |  1992-04-27  |  9KB  |  321 lines

  1. /* `alloca' standard 4.2 subroutine for 68000's and 16000's and others.
  2.    Also has _setjmp and _longjmp for pyramids.
  3.    Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Emacs.
  6.  
  7. GNU Emacs is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 1, or (at your option)
  10. any later version.
  11.  
  12. GNU Emacs is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU Emacs; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21.  
  22. /* Both 68000 systems I have run this on have had broken versions of alloca.
  23.    Also, I am told that non-berkeley systems do not have it at all.
  24.    So replace whatever system-provided alloca there may be
  25.    on all 68000 systems.  */
  26.  
  27. #define NOT_C_CODE
  28. #include "config.h"
  29.  
  30. #ifndef HAVE_ALLOCA  /* define this to use system's alloca */
  31.  
  32. #ifndef hp9000s300
  33. #ifndef m68k
  34. #ifndef m68000
  35. #ifndef WICAT
  36. #ifndef ns32000
  37. #ifndef ns16000
  38. #ifndef sequent
  39. #ifndef pyramid
  40. #ifndef ATT3B5
  41. #ifndef XENIX
  42. you
  43. lose!!
  44. #endif /* XENIX */
  45. #endif /* ATT3B5 */
  46. #endif /* pyramid */
  47. #endif /* sequent */
  48. #endif /* ns32000 */
  49. #endif /* ns16000 */
  50. #endif /* WICAT */
  51. #endif /* m68000 */
  52. #endif /* m68k */
  53. #endif /* hp9000s300 */
  54.  
  55.  
  56. #if defined (hp9000s300) || defined (mot_delta)
  57. #ifdef mot_delta
  58.     file "alloca.s"
  59. ; This syntax is what pot@fly.cnuce.cnr.it says we should use.
  60.     global    alloca
  61. alloca:
  62. #endif
  63. #ifdef OLD_HP_ASSEMBLER
  64.     data
  65.     text
  66.     globl    _alloca
  67. _alloca    
  68.     move.l    (sp)+,a0    ; pop return addr from top of stack
  69.     move.l    (sp)+,d0    ; pop size in bytes from top of stack
  70.     add.l    #ROUND,d0    ; round size up to long word
  71.     and.l    #MASK,d0    ; mask out lower two bits of size
  72.     sub.l    d0,sp        ; allocate by moving stack pointer
  73.     tst.b    PROBE(sp)    ; stack probe to allocate pages
  74.     move.l    sp,d0        ; return pointer
  75.     add.l    #-4,sp        ; new top of stack
  76.     jmp    (a0)        ; not a normal return
  77. MASK    equ    -4        ; Longword alignment
  78. ROUND    equ    3        ; ditto
  79. PROBE    equ    -128        ; safety buffer for C compiler scratch
  80.     data
  81. #else /* new hp assembler syntax */
  82. /*
  83.   The new compiler does "move.m <registers> (%sp)" to save registers,
  84.     so we must copy the saved registers when we mung the sp.
  85.   The old compiler did "move.m <register> <offset>(%a6)", which
  86.     gave us no trouble
  87.  */
  88.     text
  89.     set    PROBE,-128    # safety for C frame temporaries
  90.     set    MAXREG,22    # d2-d7, a2-a5, fp2-fp7 may have been saved
  91.     global    _alloca
  92. _alloca:
  93.     mov.l    (%sp)+,%a0    # return addess
  94.     mov.l    (%sp)+,%d0    # number of bytes to allocate
  95.     mov.l    %sp,%a1        # save old sp for register copy
  96.     mov.l    %sp,%d1        # compute new sp
  97.     sub.l    %d0,%d1        # space requested
  98.     and.l    &-4,%d1        # round down to longword
  99.     sub.l    &MAXREG*4,%d1    # space for saving registers
  100.     mov.l    %d1,%sp        # save new value of sp
  101.     tst.b    PROBE(%sp)    # create pages (sigh)
  102.     mov.l    %a2,%d1        # save reg a2
  103.     mov.l    %sp,%a2
  104.     move.w    &MAXREG-1,%d0
  105. copy_regs_loop:            /* save caller's saved registers */
  106.     mov.l    (%a1)+,(%a2)+
  107.     dbra    %d0,copy_regs_loop
  108.     mov.l    %a2,%d0        # return value
  109.     mov.l    %d1,%a2        # restore a2
  110.     add.l    &-4,%sp        # adjust tos
  111.     jmp    (%a0)        # rts
  112. #endif /* new hp assembler */
  113. #else
  114. #ifdef m68k            /* SGS assembler totally different */
  115.     file    "alloca.s"
  116.     global    alloca
  117. alloca:
  118.     mov.l    (%sp)+,%a1    # pop return addr from top of stack
  119.     mov.l    (%sp)+,%d0    # pop size in bytes from top of stack
  120.     add.l    &R%1,%d0    # round size up to long word
  121.     and.l    &-4,%d0        # mask out lower two bits of size
  122.     sub.l    %d0,%sp        # allocate by moving stack pointer
  123.     tst.b    P%1(%sp)    # stack probe to allocate pages
  124.     mov.l    %sp,%a0        # return pointer as pointer
  125.     mov.l    %sp,%d0        # return pointer as int to avoid disaster
  126.     add.l    &-4,%sp        # new top of stack
  127.     jmp    (%a1)        # not a normal return
  128.     set    S%1,64        # safety factor for C compiler scratch
  129.     set    R%1,3+S%1    # add to size for rounding
  130.     set    P%1,-132    # probe this far below current top of stack
  131.  
  132. #else /* not m68k */
  133.  
  134. #ifdef m68000
  135.  
  136. #ifdef WICAT
  137. /*
  138.  * Registers are saved after the corresponding link so we have to explicitly
  139.  * move them to the top of the stack where they are expected to be.
  140.  * Since we do not know how many registers were saved in the calling function
  141.  * we must assume the maximum possible (d2-d7,a2-a5).  Hence, we end up
  142.  * wasting some space on the stack.
  143.  *
  144.  * The large probe (tst.b) attempts to make up for the fact that we have
  145.  * potentially used up the space that the caller probed for its own needs.
  146.  */
  147.     .procss m0
  148.     .config "68000 1"
  149.     .module    _alloca
  150. MAXREG:    .const    10
  151.     .sect    text
  152.     .global    _alloca
  153. _alloca:
  154.     move.l    (sp)+,a1    ; pop return address
  155.     move.l    (sp)+,d0    ; pop allocation size
  156.     move.l    sp,d1        ; get current SP value
  157.     sub.l    d0,d1        ; adjust to reflect required size...
  158.     sub.l    #MAXREG*4,d1    ; ...and space needed for registers
  159.     and.l    #-4,d1        ; backup to longword boundry
  160.     move.l    sp,a0        ; save old SP value for register copy
  161.     move.l    d1,sp        ; set the new SP value
  162.     tst.b    -4096(sp)    ; grab an extra page (to cover caller)
  163.     move.l    a2,d1        ; save callers register
  164.     move.l    sp,a2
  165.     move.w    #MAXREG-1,d0    ; # of longwords to copy
  166. loop:    move.l    (a0)+,(a2)+    ; copy registers...
  167.     dbra    d0,loop        ; ...til there are no more
  168.     move.l    a2,d0        ; end of register area is addr for new space
  169.     move.l    d1,a2        ; restore saved a2.
  170.     addq.l    #4,sp        ; caller will increment sp by 4 after return.
  171.     move.l    d0,a0        ; return value in both a0 and d0.
  172.     jmp    (a1)
  173.     .end    _alloca
  174. #else
  175.  
  176. /* Some systems want the _, some do not.  Win with both kinds.  */
  177. .globl    _alloca
  178. _alloca:
  179. .globl    alloca
  180. alloca:
  181.     movl    sp@+,a0
  182.     movl    a7,d0
  183.     subl    sp@,d0
  184.     andl    #~3,d0
  185.     movl    d0,sp
  186.     tstb    sp@(0)        /* Make stack pages exist  */
  187.                 /* Needed on certain systems
  188.                    that lack true demand paging */
  189.     addql    #4,d0
  190.     jmp    a0@
  191.  
  192. #endif /* not WICAT */
  193. #endif /* m68000 */
  194. #endif /* not m68k */
  195. #endif /* not hp9000s300 */
  196.  
  197. #if defined (ns16000) || defined (ns32000)
  198.  
  199.     .text
  200.     .align    2
  201. /* Some systems want the _, some do not.  Win with both kinds.  */
  202. .globl    _alloca
  203. _alloca:
  204. .globl    alloca
  205. alloca:
  206.  
  207. /* Two different assembler syntaxes are used for the same code
  208.     on different systems.  */
  209.  
  210. #ifdef sequent
  211. #define IM
  212. #define REGISTER(x) x
  213. #else
  214. #define IM $
  215. #define REGISTER(x) 0(x)
  216. #endif
  217.  
  218. /*
  219.  * The ns16000 is a little more difficult, need to copy regs.
  220.  * Also the code assumes direct linkage call sequence (no mod table crap).
  221.  * We have to copy registers, and therefore waste 32 bytes.
  222.  *
  223.  * Stack layout:
  224.  * new    sp ->    junk    
  225.  *         registers (copy)
  226.  *    r0 ->    new data        
  227.  *         |       (orig retval)
  228.  *         |      (orig arg)
  229.  * old  sp ->    regs      (orig)
  230.  *        local data
  231.  *    fp ->    old fp
  232.  */
  233.  
  234.     movd    tos,r1        /*  pop return addr */
  235.     negd    tos,r0        /*  pop amount to allocate */
  236.     sprd    sp,r2
  237.     addd    r2,r0
  238.     bicb    IM/**/3,r0    /*  4-byte align */
  239.     lprd    sp,r0
  240.     adjspb    IM/**/36    /*  space for regs, +4 for caller to pop */
  241.     movmd    0(r2),4(sp),IM/**/4    /*  copy regs */
  242.     movmd    0x10(r2),0x14(sp),IM/**/4
  243.     jump    REGISTER(r1)    /* funky return */
  244. #endif /* ns16000 or ns32000. */
  245.  
  246. #ifdef pyramid
  247.  
  248. .globl _alloca
  249.  
  250. _alloca: addw $3,pr0    # add 3 (dec) to first argument
  251.     bicw $3,pr0    # then clear its last 2 bits
  252.     subw pr0,sp    # subtract from SP the val in PR0
  253.     andw $-32,sp    # keep sp aligned on multiple of 32.
  254.     movw sp,pr0    # ret. current SP
  255.     ret
  256.  
  257. #ifdef PYRAMID_OLD /* This isn't needed in system version 4.  */
  258. .globl __longjmp
  259. .globl _longjmp
  260. .globl __setjmp
  261. .globl _setjmp
  262.  
  263. __longjmp: jump _longjmp
  264. __setjmp:  jump _setjmp
  265. #endif
  266.  
  267. #endif /* pyramid */
  268.  
  269. #ifdef ATT3B5
  270.  
  271.     .align 4
  272.     .globl alloca
  273.  
  274. alloca:
  275.     movw %ap, %r8
  276.     subw2 $9*4, %r8
  277.     movw 0(%r8), %r1    /* pc */
  278.     movw 4(%r8), %fp
  279.     movw 8(%r8), %sp
  280.     addw2 %r0, %sp /* make room */
  281.     movw %sp, %r0 /* return value */
  282.     jmp (%r1) /* continue... */
  283.  
  284. #endif /* ATT3B5 */
  285.  
  286. #ifdef XENIX
  287.  
  288. .386
  289.  
  290. _TEXT segment dword use32 public 'CODE'
  291. assume   cs:_TEXT
  292.  
  293. ;-------------------------------------------------------------------------
  294.  
  295. public _alloca
  296. _alloca proc near
  297.  
  298.     pop    ecx        ; return address
  299.     pop    eax        ; amount to alloc
  300.     add    eax,3        ; round it to 32-bit boundary
  301.     and    al,11111100B    ;
  302.     mov    edx,esp        ; current sp in edx
  303.     sub    edx,eax        ; lower the stack
  304.     xchg    esp,edx        ; start of allocation in esp, old sp in edx
  305.     mov    eax,esp        ; return ptr to base in eax
  306.     push    [edx+8]        ; save poss. stored reg. values (esi,edi,ebx)
  307.     push    [edx+4]        ;  on lowered stack
  308.     push    [edx]        ;
  309.     sub    esp,4        ; allow for 'add esp, 4'
  310.     jmp    ecx        ; jump to return address
  311.  
  312. _alloca endp
  313.  
  314. _TEXT    ends
  315.  
  316. end
  317.  
  318. #endif /* XENIX */
  319.  
  320. #endif /* not HAVE_ALLOCA */
  321.